require("../models/relation")
require("./publicFn/asyncExits")
const {
    async
} = require("validate.js")
const init = require("../util/init")


/**
 * 创建管理员
 * @param {Object} admin 管理员信息对象
 * @param {string} admin.adminId 学工号
 * @param {string} admin.loginPwd 密码
 * @param {string} admin.avatar 头像 非必填
 * @param {string} admin.phone 手机号
 * @param {string} admin.Nickname 名称
 * @param {string} admin.authentication 0: 超级管理员 1:普通管理员
 * @returns {Object} {adminId: res.toJSON().adminId, text: `注册成功 学工号:${res.toJSON().adminId}`}
 */
exports.addAdmin = async function (admin) {
    admin = init.pick(admin, "adminId", "loginPwd", "avatar", "phone", "Nickname", "authentication")
    // 验证学工号和名字是否在学工表中
    init.validate.validators.JobNumberExist = async function () {
        const res = await init.JobNumber.findOne({
            where: {
                JobNumberId: admin.adminId,
                JobName: admin.Nickname
            }
        })
        if (res) {
            return
        }
        return "is not exist"
    }
    // 验证学工号和名字是否在管理员信息表中
    init.validate.validators.AdminInfonExist = async function () {
        const res = await init.AdminInfon.findOne({
            where: {
                adminId: admin.adminId,
                Nickname: admin.Nickname
            }
        })
        if (!res) {
            return
        }
        return "is exist"
    }
    const rule = {
        adminId: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            AdminInfonExist: true,
            JobNumberExist: true,
        },
        loginPwd: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            length: {
                minimum: 6,
                maximum: 10,
            }
        },
        avatar: {
            type: "string",
        },
        phone: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            format: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
        },
        Nickname: {
            presence: {
                allowEmpty: false
            },
            type: "string",
        },
        authentication: {
            presence: {
                allowEmpty: false
            },
            type: "number"
        }
    }
    try {
        await init.validate.async(admin, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    

        admin.loginPwd = init.md5(admin.loginPwd)
        admin.avatar = admin.avatar ? admin.avatar : "/upload/admin.webp"
        const res = await init.AdminInfon.create(admin)
        return {
            adminId: res.toJSON().adminId,
            text: `注册成功 学工号:${res.toJSON().adminId}`

        }
 


}



/**
 * 获取已有的管理员信息
 * @param {number} authentication 权限
 * @returns {Array} 管理员信息数组 
 */

exports.getAdmin = async function (authentication) {
    const rule = {
        authentication: {
            type: "number",
        }
    }

    try {
        const Exits = init.validate({
            authentication
        }, rule)
        if (Exits) {
            throw Exits
        }
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    const where = {};
    if (authentication) {
        where.authentication = authentication
    }
    const res = await init.AdminInfon.findAll({
        attributes: ["id", "avatar", "adminId", "Nickname", "phone", "authentication"],
        where,
        include: [{
            model: init.Dormitory,
            attributes: ["id", "DormitoryName"]
        }]
    })
    const reslut = JSON.parse(JSON.stringify(res))
    reslut.forEach(item => {
        if (item.authentication === 0) {
            item.Dormitories = -1
        }
    })
    return reslut
}

/**
 * 重置管理员密码
 * @param {Object} admin 用户提交的数据对象
 * @param {string} admin.adminId 学工号
 * @param {string} admin.phone 手机号
 * @param {string} admin.Nickname 姓名
 * @param {string} admin.newPwd 新密码
 * @returns {Object} 修改成功对象或失败对象
 */
exports.resetting = async function (admin) {
    admin = init.pick(admin, "adminId", "phone", "Nickname", "newPwd")
    init.validate.validators.AdminInfonExist = async function () {
        const res = await init.AdminInfon.findOne({
            where: {
                adminId: admin.adminId,
                Nickname: admin.Nickname,
                authentication: 1
            }
        })
        if (res) {
            return
        }
        return "is not exist or Insufficient permissions"
    }
    const rule = {
        adminId: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            AdminInfonExist: true

        },
        phone: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            format: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
        },
        Nickname: {
            presence: {
                allowEmpty: false
            },
            type: "string",
        },
        newPwd: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            length: {
                minimum: 6,
                maximum: 10,
            }
        }
    }
    try {
        await init.validate.async(admin, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    

        const res = await init.AdminInfon.update({
            loginPwd: init.md5(admin.newPwd)
        }, {
            where: {
                adminId: admin.adminId,
                phone: admin.phone,
                Nickname: admin.Nickname
            }
        })
        if (JSON.parse(JSON.stringify(res))[0] === 1) {
            return {
                adminId: admin.adminId,
                nickname: admin.Nickname,
                phone: admin.phone,
                text: "重置密码成功"
            }
        }
        return {
            text: "修改失败"
        }
  

}

/**
 * 查询宿舍费
 * @param {number} peopleNum 几人间
 * @param {Object} 返回房间价格对象
 */
exports.getRoomRate = async function (peopleNum) {
    const rule = {
        peopleNum: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        }
    }

    try {
        const Exits = init.validate({
            peopleNum
        }, rule)
        if (Exits) {
            throw Exits
        }
        const res = await init.RoomRate.findAll({
            where: {
                peopleNum
            }
        })
        if (JSON.parse(JSON.stringify(res)).length !== 0) {
            return {
                ...JSON.parse(JSON.stringify(res))['0'],
                isExist: 1
            }
        }
        return {
            text: "没有查找到,需要添加",
            isExist: 0
        }
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
}

/**
 * 添加宿舍费
 * @param {number} peopleNum 几人间
 * @param {number} price 价格
 * @returns {number} 返回添加的对象.id
 */
exports.addRoomRate = async function (peopleNum, price) {
    init.validate.validators.RoomRateExits = async function (value) {
        const res = await init.RoomRate.findOne({
            where: {
                peopleNum: value
            }
        })
        if (!res) {
            return
        }
        return "is exits"
    }

    const rule = {
        peopleNum: {

            presence: {
                allowEmpty: false
            },
            type: "number",
            RoomRateExits: true,
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        },
        price: {

            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }

        }
    }
    try {
        await init.validate.async({
            peopleNum,
            price
        }, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   
        const res = await init.RoomRate.create({
            peopleNum,
            price
        })
        return res.toJSON().id
   


}



/**
 * 创建宿舍楼
 * @param {Object} DormitoryObj 楼层对象
 * @param {string} DormitoryObj.DormitoryName 楼层名称
 * @param {number} DormitoryObj.floorNum 楼层数
 * @param {number} DormitoryObj.roomNum 房间数
 * @param {number} DormitoryObj.fewPeople 每间多少人,
 * @param {number} DormitoryObj.RoomRateId 宿舍费id,
 * @returns {Object} 添加成功对象
 */
exports.addDormitory = async function (DormitoryObj) {
    DormitoryObj = init.pick(DormitoryObj, "DormitoryName", "floorNum", "roomNum", "fewPeople", "RoomRateId")
    // 验证宿舍楼名称是否冲突
    init.validate.validators.DormitoryNameExits = async function (value) {

        const res = await init.Dormitory.findOne({
            where: {
                DormitoryName: value
            }
        })

        if (!res) {
            return
        }
        return "DormitoryName conflict"
    }
    const rule = {
        DormitoryName: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            length: {
                maximum: 5,
                minimum: 2
            },
            DormitoryNameExits: true
        },
        floorNum: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }

        },
        roomNum: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        },
        fewPeople: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }

        },
        RoomRateId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },

        }
    }
    try {
        await init.validate.async(DormitoryObj, rule)
        // 验证宿舍费id和每间几个人有无对应关系
        const isCorr = await init.RoomRate.findOne({
            where: {
                id: DormitoryObj.RoomRateId,
                peopleNum: DormitoryObj.fewPeople
            }
        })
        if (!isCorr) {
            throw "fewPeople and RoomRateId No corresponding relationship"
        }
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   


        DormitoryObj.dormitoryCapacity = DormitoryObj.floorNum * DormitoryObj.roomNum * DormitoryObj.fewPeople
        DormitoryObj.dormitoryresided = 0

        const addDormitory = await init.Dormitory.create(DormitoryObj)
        // 楼层数据
        let FloorArr = new Array(DormitoryObj.floorNum).fill({}).map((item, index) => {
            return {
                floorNumber: index + 1 + "层",
                roomNum: DormitoryObj.roomNum,
                floorCapacity: DormitoryObj.roomNum * DormitoryObj.fewPeople,
                floorResided: 0,
                DormitoryId: addDormitory.toJSON().id
            }
        })

        // 添加楼层
        const addFloor = await init.Floor.bulkCreate(FloorArr)


        // 房间数据
        let floor = 0
        let RoomNum = 0
        let FloorId = JSON.parse(JSON.stringify(addFloor))[0].id - 1 // 外键Floorid
        const RoomArr = new Array(DormitoryObj.floorNum * DormitoryObj.roomNum).fill({}).map((item, index) => {
            if (index % DormitoryObj.roomNum === 0) {
                floor++;
                RoomNum = 0
                FloorId++
            }
            RoomNum++;
            let roomNo = floor + RoomNum.toString().padStart(2, 0)
            return {
                roomNo,
                roomCapacity: DormitoryObj.fewPeople,
                roomResided: 0,
                FloorId
            }
        })

        // 添加宿舍表
        const addRoom = await init.RoomNo.bulkCreate(RoomArr)
        // 床位数据
        let RoomNoId = JSON.parse(JSON.stringify(addRoom))[0].id - 1; // 房间id
        let bednumberId = 0;
        const bedNumArr = new Array(DormitoryObj.dormitoryCapacity).fill({}).map((item, index) => {
            if (index % DormitoryObj.fewPeople === 0) {
                RoomNoId++;
                bednumberId = 0;
            }
            bednumberId++;
            return {
                bednumberId: bednumberId + "号床",
                isPeople: 0,
                RoomNoId
            }
        })
        // 添加床位

        const addBedNum = await init.Bednumber.bulkCreate(bedNumArr);
        return {
            id: addDormitory.toJSON().id,
            dormitoryName: DormitoryObj.DormitoryName,
            floorNum: DormitoryObj.floorNum,
            roomNum: DormitoryObj.roomNum,
            fewPeople: DormitoryObj.fewPeople,
            capacity: DormitoryObj.dormitoryCapacity,
            text: "成功"
        }
   

}

/**
 * 分配保洁人员
 * @param {Object} cleaningObj 用户提供的数据
 * @param {number} cleaningObj.floorId 楼层id,
 * @param {string} cleaningObj.cleaningId 保洁人员id
 * @returns {Object} 分配成功对象
 */
exports.allCleaning = async function (cleaningObj) {
    cleaningObj = init.pick(cleaningObj, "floorId", "cleaningId")
    // 验证保洁人员id是否存在并且没有分配
    init.validate.validators.cleaningIdExits = async function (value) {
        const res = await init.Cleaning.findOne({
            where: {
                id: value,
                FloorId: {
                    [init.Op.is]: null
                }
            }
        })
        if (res) {
            return
        }
        return "cleaningId is not Exits or Assigned"
    }
    // 验证楼层id是否分配了保洁人员
    init.validate.validators.floorIdAssigned = async function (value) {
        const res = await init.Cleaning.findOne({
            where: {
                FloorId: value
            }
        })
        if (!res) {
            return
        }
        return "Assigned"
    }
    const rule = {
        floorId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            floorIdExits: true
        },
        cleaningId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            cleaningIdExits: true,
            floorIdAssigned: true
        }
    }

    try {
        await init.validate.async(cleaningObj, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   

        const res = await init.Cleaning.update({
            FloorId: cleaningObj.floorId
        }, {
            where: {
                id: cleaningObj.cleaningId
            }
        })
        console.log(res[0]);
        if (res[0] === 1) {
            return "分配成功"
        }
    


}


/**
 * 添加保洁人员
 * @param {object} addCleanObj 用户提供的数据
 * @param {string} addCleanObj.cleaningName 保洁员工姓名
 * @param {string} addCleanObj.cleanPhone 保洁员工手机号
 * @param {string} addCleanObj.avatar 保洁员工头像
 * @param {string} addCleanObj.economize 省
 * @param {string} addCleanObj.market 市
 * @param {string} addCleanObj.distinguish 区/县
 * @returns {Object} 返回添加成功对象
 */
exports.addCleaning = async function (addCleanObj) {
    addCleanObj = init.pick(addCleanObj, "cleaningName", "cleaningPhone", "avatar", "economize", "market", "distinguish")
    init.validate.validators.PhoneExits = async function (value) {
        const res = await init.Cleaning.findOne({
            where: {
                cleaningPhone: addCleanObj.cleaningPhone
            }
        })
        if (!res) {
            return
        }
        return "is Exits"
    }
    const rule = {
        cleaningName: {
            presence: {
                allowEmpty: false
            },
            type: "string"
        },
        cleaningPhone: {
            presence: {
                allowEmpty: false
            },
            type: "string",
            format: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
            PhoneExits: true
        },
        avatar: {
            presence: {
                allowEmpty: false
            },
            type: "string"
        },
        economize: {
            presence: {
                allowEmpty: false
            },
            type: "string"
        },
        market: {
            presence: {
                allowEmpty: false
            },
            type: "string"
        },
        distinguish: {
            presence: {
                allowEmpty: false
            },
            type: "string"
        }
    }

    try {
        await init.validate.async(addCleanObj, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   


        const cleaningList = await init.Cleaning.findAll()
        // 现有的员工编号
        const cleaningNum = JSON.parse(JSON.stringify(cleaningList)).map(item => {
            return item.cleaningNumber
        })
        let newCleanNum = null; // 生成的编号
        let set = new Set(cleaningNum);
        const oldSetSize = set.size
        // 生成唯一的员工编号
        while (true) {
            newCleanNum = Math.random().toString().slice(-4)
            set.add(newCleanNum)
            if (set.size - oldSetSize === 1) {
                break;
            }
        }
        addCleanObj.cleaningNumber = newCleanNum
        addCleanObj.checkInTime = +init.moment.utc()
        const res = await init.Cleaning.create(addCleanObj)
        return {
            ...res.toJSON(),
            text: "入职成功"
        }


}


/**
 * 分配管理员
 * @param {Object} allAdminObj 用户提交数据
 * @param {number} allAdminObj.dormitoryId 宿舍楼id
 * @param {string} allAdminObj.adminInfoId 管理员id
 * @returns {string} 分配成功 
 */
exports.allAdmin = async function (allAdminObj) {
    allAdminObj = init.pick(allAdminObj, "dormitoryId", "adminInfoId")
    // 验证宿舍楼id是否已经分配了管理员
    init.validate.validators.dormitoryIdAssigned = async function (value) {
        const res = await init.Dormitory.findOne({
            where: {
                AdminInfonId: {
                    [init.Op.is]: null
                },
                id: value
            }
        })
        if (res) {
            return
        }
        return "Assigned"
    }
    // 验证管理员id是否存在并且管理员的权限不能为0
    init.validate.validators.adminInfoIdExits = async function (value) {
        const res = await init.AdminInfon.findOne({
            where: {
                id: value,
                authentication: {
                    [init.Op.not]: 0
                }
            }
        })
        if (res) {
            return
        }
        return "Assigned or not Exits or Permission mismatch"
    }

    const rule = {
        dormitoryId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            dormitoryIdExits: true,
            dormitoryIdAssigned: true
        },
        adminInfoId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            adminInfoIdExits: true,
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        }
    }

    try {
        await init.validate.async(allAdminObj, rule)

    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   

        const res = await init.Dormitory.update({
            AdminInfonId: allAdminObj.adminInfoId
        }, {
            where: {
                id: allAdminObj.dormitoryId
            }
        })
        if (res[0] === 1) {
            return "分配成功"
        }
   


}

/**
 * 管理员退出宿舍楼
 * @param {number} dormitoryId 宿舍楼id
 * @returns {string} 退出成功
 */
const quitDormitory = async function (dormitoryId) {
    const rule = {
        dormitoryId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            dormitoryIdExits: true,
        }
    }
    try {
        await init.validate.async({
            dormitoryId
        }, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
   

        const reslut = await init.Dormitory.update({
            AdminInfonId: null
        }, {
            where: {
                id: dormitoryId,
                AdminInfonId: {
                    [init.Op.not]: null
                }
            }
        })

        if (reslut[0] === 1) {
            return "退出成功"
        }
        return {
            code: 401,
            err: "dormitoryId is not exits or No allocation"
        }
   


}
exports.quitDormitory = quitDormitory
/**
 * 修改宿舍管理员
 * @param {object} reqObj 用户提供的条件对象
 * @param {number} reqObj.dormitoryId 宿舍楼id
 * @param {number} reqObj.oldAdminId 旧管理员id
 * @param {number} reqObj.newAdminId 新管理员id
 * @returns {string} 修改成功
 */
exports.updateDAdmin = async function (reqObj) {
    reqObj = init.pick(reqObj, "dormitoryId", "oldAdminId", "newAdminId")
    // 验证宿舍楼id是否已经分配了管理员
    init.validate.validators.dormitoryIdAssigned = async function (value) {
        const res = await init.Dormitory.findOne({
            where: {
                AdminInfonId: {
                    [init.Op.not]: null
                },
                id: value
            }
        })
        if (res) {
            return
        }
        return "No allocation"
    }
    // 验证管理员id是否存在并且管理员的权限不能为0
    init.validate.validators.adminInfoIdExits = async function (value) {
        const res = await init.AdminInfon.findOne({
            where: {
                id: value,
                authentication: {
                    [init.Op.not]: 0
                }
            }
        })
        if (res) {
            return
        }
        return "Assigned or not Exits or Permission mismatch"
    }
    const rule = {
        dormitoryId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            dormitoryIdExits: true,
            dormitoryIdAssigned: true
        },
        oldAdminId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            AdminExits: true
        },
        newAdminId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            },
            adminInfoIdExits: true
        }
    }
    try {
        await init.validate.async(reqObj, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    

        const reslut = await init.Dormitory.update({
            AdminInfonId: reqObj.newAdminId
        }, {
            where: {
                id: reqObj.dormitoryId
            }
        })
        if (reslut[0] === 1) {
            return "修改成功"
        }
    


}
/**
 * 删除管理员
 * @param {number} id 管理员id
 * @returns {string} 删除成功
 */
exports.deladmin = async function (id) {
    // 验证管理员id是否存在，并且且id不能为1
    init.validate.validators.adminIdExits = async function (value) {
        if (value === 1) {
            return "Cannot delete initial administrator"
        }
        const res = await init.AdminInfon.findByPk(value)
        if (res) {
            return
        }
        return "is not exits"
    }
    const rule = {
        id: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            adminIdExits: true
        }
    }
    try {
        await init.validate.async({
            id
        }, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    
        // 监测管理员id有没有接管宿舍
        const isAdminDor = await init.Dormitory.findOne({
            where: {
                AdminInfonId: id
            }
        })

        if (isAdminDor) {
            // 退出
            await quitDormitory(isAdminDor.toJSON().id)
        }
        const res = await init.AdminInfon.destroy({
            where: {
                id
            }
        })
        if (res === 1) {
            return "删除成功"
        }
    

}

/**
 * 退出楼层保洁
 * @param {object} FCObj 用户提交对象
 * @param {number} FCObj.floorId 楼层id
 * @param {number} FCObj.cleaningId 保洁员工id
 * @returns {string} 退出成功
 */
exports.quitFloorCleaning = async function (FCObj) {
    FCObj = init.pick(FCObj, "floorId", "cleaningId")
    init.validate.validators.cleaningIdExits = async (value) => {
        const res = await init.Cleaning.findOne({
            where: {
                id: value,
                FloorId: FCObj.floorId
            }
        })
        if (res) {
            return
        }
        return "is not exits or No allocation"
    }
    const rule = {
        floorId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            floorIdExits: true
        },
        cleaningId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            cleaningIdExits: true
        }
    }
    try {
        await init.validate.async(FCObj, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    

        const res = await init.Cleaning.update({
            FloorId: null
        }, {
            where: {
                id: FCObj.cleaningId
            }
        })

        if (res[0] === 1) {
            return "退出成功"
        }
   


}




/**
 * 查询保洁人员信息
 * @param {Object} cleaningObj 条件对象
 * @param {string} cleaningObj.cleaningNumber 编号
 * @param {string} cleaningObj.cleaningName 姓名
 * @param {number} cleaningObj.isRegion 1:未有工作区域 2:已有工作区域
 * 
 */
exports.cleaning = async function (cleaningObj) {
    cleaningObj = init.pick(cleaningObj, "page", "limit", "cleaningNumber", "cleaningName", "isRegion")
    const ralu = {
        page: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        },
        limit: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            numericality: {
                onlyInteger: true,
                greaterThan: 0,
            }
        },
        cleaningNumber: {
            type: "string"
        },
        cleaningName: {
            type: "string"
        },
        isRegion: {
            type: "number"
        }
    }
    try {
        const Exits = init.validate(cleaningObj, ralu)
        if (Exits) {
            throw Exits
        }
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    let where = {}

    if (cleaningObj) {
        if (cleaningObj.cleaningNumber) {
            where.cleaningNumber = cleaningObj.cleaningNumber
        }
        if (cleaningObj.cleaningName) {
            where.cleaningName = {
                [init.Op.like]: `%${cleaningObj.cleaningName}%`
            }
        }
        if (cleaningObj.isRegion) {
            where.FloorId = cleaningObj.isRegion === 1 ? {
                [init.Op.is]: null
            } : {
                [init.Op.not]: null
            }
        }
    }

    const res = await init.Cleaning.findAndCountAll({
        offset: (cleaningObj.page - 1) * cleaningObj.limit,
        limit: cleaningObj.limit,
        where,
        include: [{
            attributes: ["id", "floorNumber"],
            model: init.Floor,
            include: [{
                attributes: ["id", "DormitoryName"],
                model: init.Dormitory
            }]
        }]
    })
    let reslut = {
        total: res.count
    }
    reslut.rows = JSON.parse(JSON.stringify(res.rows)).map(itme => {
        return {
            id: itme.id,
            cleaningavatar: itme.avatar,
            cleaningNumber: itme.cleaningNumber,
            cleaningPhone: itme.cleaningPhone,
            cleaningName: itme.cleaningName,
            responsible: itme.Floor ? {
                dormitoryId: itme.Floor.Dormitory.id,
                dormitoryName: itme.Floor.Dormitory.DormitoryName,
                floorID: itme.Floor.id,
                floorNumber: itme.Floor.floorNumber
            } : null,
            address: {
                economize: itme.economize,
                market: itme.market,
                distinguish: itme.distinguish
            }
        }
    })
    return reslut



}

/**
 * 修改楼层保洁人员
 * @param {Object} cleaningObj 条件对象
 * @param {number} floorId 楼层id
 * @param {number} oldCleaningId 旧保洁人员id
 * @param {number} newCleaningId 新保洁人员id
 */
exports.updateFCleaning = async function (cleaningObj) {
    cleaningObj = init.pick(cleaningObj, "floorId", "oldCleaningId", "newCleaningId")
    init.validate.validators.oldCleaningIdExits = async (value) => {
        const res = await init.Cleaning.findOne({
            where: {
                id: value,
                FloorId: cleaningObj.floorId
            }
        })
        if (res) {
            return
        }
        return "not Exist"
    }
    init.validate.validators.newCleaningIdExits = async (value) => {
        const res = await init.Cleaning.findOne({
            where: {
                id: value
            }
        })
        if (res) {
            return
        }
        return "not Exist"
    }
    const rule = {
        floorId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            floorIdExits: true
        },
        oldCleaningId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            oldCleaningIdExits: true
        },
        newCleaningId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            newCleaningIdExits: true
        }
    }
    try {
        await init.validate.async(cleaningObj, rule)
    } catch (err) {
        return {
            code: 401,
            err
        }
    }
    
        const reslut = await init.Cleaning.update({
            FloorId: null
        }, {
            where: {
                id: cleaningObj.oldCleaningId
            }
        })
        const res = await init.Cleaning.update({
            FloorId: cleaningObj.floorId
        }, {
            where: {
                id: cleaningObj.newCleaningId
            }
        })
        if (reslut[0] === 1 && res[0] === 1) {
            return "修改成功"
        }
    

}

/**
 * 获取入住信息
 * @param {Number} page 页码
 * @param {Number} limit 多少条数据
 * @param {Object} keyword 查询的对象 {dormitoryId: "宿舍楼id",floorNumber : "楼层id",roomNo: "宿舍id",loginId: "学号",nickname: "学生姓名"}
 */
exports.getCheckInRecord = async function (page = 1, limit = 10, keyword = {}) {
    const ralu = {
        page: {
            presence: {
                allowEmpty: false
            },
            type: "number",
        },
        limit: {
            presence: {
                allowEmpty: false
            },
            type: "number",
        },
        keyword: {
            type: "object",
        }
    }
    const keywordExits = {
        dormitoryId: {
            type: "number"
        },
        floorId: {
            type: "number"
        },
        roomNoId: {
            type: "number"
        },
        loginId: {
            type: "string"
        },
        nickname: {
            type: "string"
        }
    }
    try {
        const Exits = init.validate({
            page,
            limit,
            keyword
        }, ralu)
        const WExits = init.validate(keyword, keywordExits)
        if (Exits) {
            throw Exits
        }
        if (WExits) {
            throw WExits
        }
    } catch (err) {
        console.log(err);
        return {
            code: 401,
            err
        }
    }
    

        const res = await init.StudentSInfon.findAndCountAll({
            distinct: true,
            offset: (page - 1) * limit,
            limit: limit,
            order: [
                ['id', 'ASC']
            ],
            attributes: ["id", "studentId", "Nickname", "phone", "checkInTime", "OrderNo"],
            where: {
                [init.Op.and]: [{
                        studentId: keyword.loginId ? keyword.loginId : {
                            [init.Op.not]: null
                        }
                    },
                    {
                        Nickname: keyword.nickname ? {
                            [init.Op.like]: `%${keyword.nickname}%`
                        } : {
                            [init.Op.not]: null
                        }
                    }
                ]
            },
            include: [{
                model: init.Bednumber,
                attributes: ["id", "bednumberId"],
                required: true,
                include: [{
                    model: init.RoomNo,
                    attributes: ["id", "roomNo"],
                    required: true,
                    where: {
                        id: keyword.roomNoId ? keyword.roomNoId : {
                            [init.Op.not]: null
                        }
                    },
                    include: [{
                        model: init.Floor,
                        attributes: ["id", "floorNumber"],
                        required: true,
                        where: {
                            id: keyword.floorId ? keyword.floorId : {
                                [init.Op.not]: null
                            }
                        },
                        include: [{
                            model: init.Dormitory,
                            attributes: ["id", "DormitoryName"],
                            required: true,
                            where: keyword.dormitoryId ? {
                                id: keyword.dormitoryId
                            } : {}
                        }]
                    }]
                }]
            }],
        })
        console.log(JSON.parse(JSON.stringify(res)).rows);
        let reslut = {}
        reslut.total = JSON.parse(JSON.stringify(res)).count
        reslut.rows = JSON.parse(JSON.stringify(res)).rows.map(itme => {

            return {
                id: itme.id,
                studentID: itme.studentId,
                studentName: itme.Nickname,
                OrderNo: itme.OrderNo,
                phone: itme.phone,
                checkInTime: itme.checkInTime,
                dormitoryId: itme.Bednumber.RoomNo.Floor.Dormitory.id,
                dormitoryName: itme.Bednumber.RoomNo.Floor.Dormitory.DormitoryName,
                floorID: itme.Bednumber.RoomNo.Floor.id,
                floorNumber: itme.Bednumber.RoomNo.Floor.floorNumber,
                roomNoId: itme.Bednumber.RoomNo.id,
                roomNo: itme.Bednumber.RoomNo.roomNo,
                bednumberId: itme.Bednumber.id,
                bednumber: itme.Bednumber.bednumberId,
            }
        })
        return reslut
   

}

/**
 * 获取班级信息
 */
exports.getClass = async function (condition) {
    const ralu = {
        condition: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            inclusion: [0, 1]
        }
    }
    try {
        const Exits = init.validate({
            condition
        }, ralu)
        if (Exits) {
            throw Exits
        }
    } catch (err) {
        console.log(err);
        return {
            code: 401,
            err
        };
    }
    const classInfo = await init.classInfo.findAll({
        attributes: ["id", "className", "classPeople"],
    });
    const results = await Promise.all(JSON.parse(JSON.stringify(classInfo)).map(async (item) => {
        const dormitories = await init.Dormitory.findAll({
            attributes: [
                ["id", "dormitoryId"],
                ["DormitoryName", "label"]
            ],
            include: [{
                attributes: [
                    ["id", "floorId"],
                    ["floorNumber", "label"]
                ],
                model: init.Floor,
                required: true,
                include: [{
                    attributes: [
                        ["id", "RoomNoId"],
                        ["RoomNo", "label"], "classInfoId"
                    ],
                    required: true,
                    model: init.RoomNo,
                    where: {
                        classInfoId: item.id
                    }
                }]
            }]
        });

        return {
            ...item,
            children: dormitories
        };
    }));
    const newData = JSON.parse(JSON.stringify(results)).filter(item => {
        if (condition) {
            return item.children.length === 0
        } else {
            return item.children.length !== 0
        }
    }).map(item => {
        return {
            id: item.id,
            className: item.className,
            classPeople: item.classPeople,
            children: item.children.map(itD => {

                return {
                    dormitoryId: itD.dormitoryId,
                    label: itD.label,
                    children: itD.Floors.map(itF => { // 假设itD对象有一个Floors数组属性
                        return {
                            floorId: itF.floorId,
                            label: itF.label,
                            children: itF.RoomNos.map(itR => { // 假设itF对象有一个RoomNos数组属性
                                return {
                                    RoomNoId: itR.RoomNoId,
                                    label: itR.label // 或其他你需要的属性
                                };
                            })
                        };
                    })
                };
            })
        };
    });
    return newData;

}


/**
 * 查询未配的宿舍
 */
exports.getUnallocated = async function () {
        const res = await init.Dormitory.findAll({
            include: [{
                model: init.Floor,
                required: true,
                include: [{
                    required: true,
                    model: init.RoomNo,
                    where: {
                        classInfoId: {
                            [init.Op.is]: null
                        }
                    }
                }]
            }]
        })
        const resluts = JSON.parse(JSON.stringify(res)).map(item => {
            return {
                id: item.id,
                label: item.DormitoryName,
                children: item.Floors.map(itF => {
                    return {
                        id: itF.id,
                        label: itF.floorNumber,
                        children: itF.RoomNos.map(itR => {
                            return {
                                id: itR.id,
                                label: itR.roomNo + ` (${itR.roomCapacity}人)`,
                                roomCapacity: itR.roomCapacity
                            }
                        }),

                    }
                })
            }
        })
        return resluts
    
}

/**
 * 分配宿舍
 * @param {Array} RoomArr 宿舍id数组
 * @param {Number} classId 班级id
 */
exports.distributionRoom = async function (RoomArr, classId) {
    // 验证宿舍id是否存在(数组)
    init.validate.validators.roomNoArrExits = async function (value) {
        const res = await init.RoomNo.findAll({
            where: {
                id: {
                    [init.Op.in]: value,
                },
                classInfoId: {
                    [init.Op.is]: null
                }
            }
        })
        if (JSON.parse(JSON.stringify(res)).length === value.length) {
            return
        }
        return "One of the items in the array does not exist"
    }
    const ralu = {
        RoomArr: {
            presence: {
                allowEmpty: false
            },
            type: "array",
            roomNoArrExits: true
        },
        classId: {
            presence: {
                allowEmpty: false
            },
            type: "number",
            classInfoExits: true
        }
    }
    try{
        await init.validate.async({
            RoomArr,
            classId
        }, ralu)
    }catch(err){
        return{
            code: 401,
            err
        }
    }
   
            const reslut = await init.RoomNo.update({
                classInfoId: classId
            }, {
                where: {
                    id: {
                        [init.Op.in]: RoomArr
                    }
                }
            })
            if (reslut.length !== 0) {
                return "分配成功"
            }
   
}